home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Ebooks / Thinking in C++ V2 / C26 / MemCheck.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-25  |  4.1 KB  |  164 lines

  1. //: C26:MemCheck.cpp {O}
  2. // From Thinking in C++, 2nd Edition
  3. // Available at http://www.BruceEckel.com
  4. // (c) Bruce Eckel 1999
  5. // Copyright notice in Copyright.txt
  6. // Memory allocation tester
  7. #include <cstdlib>
  8. #include <cstring>
  9. #include <cstdio>
  10. using namespace std;
  11. // MemCheck.h must not be included here
  12.  
  13. // Output file object using cstdio
  14. // (cout constructor calls malloc())
  15. class OFile {
  16.   FILE* f;
  17. public:
  18.   OFile(char* name) : f(fopen(name, "w")) {}
  19.   ~OFile() { fclose(f); }
  20.   operator FILE*() { return f; }
  21. };
  22. extern OFile memtrace;
  23. // Comment out the following to send all the
  24. // information to the trace file:
  25. #define memtrace stdout
  26.  
  27. const unsigned long _pool_sz = 50000L;
  28. static unsigned char _memory_pool[_pool_sz];
  29. static unsigned char* _pool_ptr = _memory_pool;
  30.  
  31. void* getmem(size_t sz) {
  32.   if(_memory_pool + _pool_sz - _pool_ptr < sz) {
  33.     fprintf(stderr,
  34.            "Out of memory. Use bigger model\n");
  35.     exit(1);
  36.   }
  37.   void* p = _pool_ptr;
  38.   _pool_ptr += sz;
  39.   return p;
  40. }
  41.  
  42. // Holds information about allocated pointers:
  43. class MemBag { 
  44. public:
  45.   enum type { Malloc, New };
  46. private:
  47.   char* typestr(type t) {
  48.     switch(t) {
  49.       case Malloc: return "malloc";
  50.       case New: return "new";
  51.       default: return "?unknown?";
  52.     }
  53.   }
  54.   struct M {
  55.     void* mp;  // Memory pointer
  56.     type t;     // Allocation type
  57.     char* file; // File name where allocated
  58.     int line;  // Line number where allocated
  59.     M(void* v, type tt, char* f, int l)
  60.       : mp(v), t(tt), file(f), line(l) {}
  61.   }* v;
  62.   int sz, next;
  63.   static const int increment = 50 ;
  64. public:
  65.   MemBag() : v(0), sz(0), next(0) {}
  66.   void* add(void* p, type tt = Malloc,
  67.             char* s = "library", int l = 0) {
  68.     if(next >= sz) {
  69.       sz += increment;
  70.       // This memory is never freed, so it
  71.       // doesn't "get involved" in the test:
  72.       const int memsize = sz * sizeof(M);
  73.       // Equivalent of realloc, no registration:
  74.       void* p = getmem(memsize);
  75.       if(v) memmove(p, v, memsize);
  76.       v = (M*)p;
  77.       memset(&v[next], 0,
  78.              increment * sizeof(M));
  79.     }
  80.     v[next++] = M(p, tt, s, l);
  81.     return p;
  82.   }
  83.   // Print information about allocation:
  84.   void allocation(int i) {
  85.     fprintf(memtrace, "pointer %p"
  86.       " allocated with %s",
  87.       v[i].mp, typestr(v[i].t));
  88.     if(v[i].t == New)
  89.       fprintf(memtrace, " at %s: %d",
  90.         v[i].file, v[i].line);
  91.     fprintf(memtrace, "\n");
  92.   }
  93.   void validate(void* p, type T = Malloc) {
  94.     for(int i = 0; i < next; i++)
  95.       if(v[i].mp == p) {
  96.         if(v[i].t != T) {
  97.           allocation(i);
  98.           fprintf(memtrace,
  99.           "\t was released as if it were "
  100.           "allocated with %s \n", typestr(T));
  101.         }
  102.         v[i].mp = 0;  // Erase it
  103.         return;
  104.       }
  105.     fprintf(memtrace,
  106.     "pointer not in memory list: %p\n", p);
  107.   }
  108.   ~MemBag() {
  109.     for(int i = 0; i < next; i++)
  110.       if(v[i].mp != 0) {
  111.         fprintf(memtrace,
  112.         "pointer not released: ");
  113.         allocation(i);
  114.       }
  115.   }
  116. };
  117. extern MemBag MEMBAG_;
  118.  
  119. void* malloc(size_t sz) {
  120.   void* p = getmem(sz);
  121.   return MEMBAG_.add(p, MemBag::Malloc);
  122. }
  123.  
  124. void* calloc(size_t num_elems, size_t elem_sz) {
  125.   void* p = getmem(num_elems * elem_sz);
  126.   memset(p, 0, num_elems * elem_sz);
  127.   return MEMBAG_.add(p, MemBag::Malloc);
  128. }  
  129.  
  130. void* realloc(void* block, size_t sz) {
  131.   void* p = getmem(sz);
  132.   if(block) memmove(p, block, sz);
  133.   return MEMBAG_.add(p, MemBag::Malloc);
  134. }
  135.  
  136. void free(void* v) { 
  137.   MEMBAG_.validate(v, MemBag::Malloc);
  138. }
  139.  
  140. void* operator new(size_t sz) {
  141.   void* p = getmem(sz);
  142.   return MEMBAG_.add(p, MemBag::New);
  143. }
  144.  
  145. void*
  146. operator new(size_t sz, char* file, int line) {
  147.   void* p = getmem(sz);
  148.   return MEMBAG_.add(p, MemBag::New, file,line);
  149. }
  150.  
  151. void operator delete(void* v) {
  152.   MEMBAG_.validate(v, MemBag::New);
  153. }
  154.  
  155. MemBag MEMBAG_;
  156. // Placed here so the constructor is called
  157. // AFTER that of MEMBAG_ :
  158. #ifdef memtrace
  159. #undef memtrace
  160. #endif
  161. OFile memtrace("memtrace.out");
  162. // Causes 1 "pointer not in memory list" message
  163. ///:~
  164.